var koa = require('koa');
var template = require('art-template');
var serve = require('koa-static');
var send = require('koa-send');
var path = require('path');
var fs = require('fs');
var readline  = require('readline');  
var stream    = require('stream');
var streamFile = function(filename){
    var instream  = fs.createReadStream(filename);
    var outstream = new stream;
    return readline.createInterface(instream, outstream);
}

var OPTS = {
	src_path : path.resolve(__dirname, '../src'), // 源码目录
	compiled_path_name : '.auto-compiled',
	compiled_save_path : path.resolve(__dirname, './.auto-compiled'), // 服务端自动编译后的保存目录
	statics_path : path.resolve(__dirname, '../public'), // 静态资源目录
	view_path : path.resolve(__dirname, './view'), // 视图目录
	view_ext : '.html', // 视图文件后缀
}

// App每次启动的时候去编译src目录的所有文件到compiled目录
var fu = require('file-utils');
var Babel = require('babel-core');
fu.recurse(OPTS.src_path, function(p, r, s, n) {
	p = path.resolve(p, ".");
	var _extname = p.substr(p.lastIndexOf('.'));
	if (_extname !== '.jsx') {
		return false;
	}
	var _relative = p.replace(r, '').replace(n, '').replace(/\\/g, '/');// 文件所在相对目录
	var dest = path.join(OPTS.compiled_save_path, p.replace(r, '').replace('.jsx', '.js'));
	fu.copy(p, dest, {encoding:'utf-8', process: function(contents, srcp) {
		var allowToCopy = true;
		var destcontents = null;
		try {
			destcontents = fu.read(dest);
		} catch (e){}
		
		try{
			var newcontents = Babel.transform(contents, { presets:['react'] }).code;
			if (newcontents.indexOf('ReactDOM.render(') >= 0) {
				var _d = [];
				_relative.split('/').forEach(function(it, i){
					if (it && it.trim != '') {
						_d.push('..');
					}
				}); 
				newcontents = newcontents
					.replace(/require\s*\(\s*['"]jquery['"]\s*\)/g, 'require(\''+_d.join('/')+'/../../public/js/jq-delegate.js\')')
					.replace(/require\s*\(\s*['"]react\-dom['"]\s*\)/g, 'require(\'react-dom/server\')')
					.replace('ReactDOM', 'ReactDOMServer')
					.replace('ReactDOM.render(', 'var _html = ReactDOMServer.renderToString(')
					.replace(/,\s*document\..*\)/g, ')');
				newcontents = newcontents + '\r\nvar _ajax = typeof($) != \'undefined\' ? $.__cache : {};\r\nmodule.exports={\r\n\thtml:_html,\r\n\tajax:_ajax\r\n}';
			} 
			newcontents = newcontents.replace(/require\s*\(['"].[^'"]*\.css\s*['"]\)\s*/g, '//replace by server.');
			
			allowToCopy = newcontents !== destcontents;
		} catch (er) {
			console.error(er);
		}
		
		return allowToCopy ? newcontents : false;
	}});
});
 
var app = koa();

// app settings
app.name = 'My First KOA Project';
app.env = 'development';
// template config 
template.config('base', OPTS.view_path);
template.config('extname', OPTS.view_ext);

// static files
app.use(serve(OPTS.statics_path));

// handle all request that match '*.html' or '/' by template renderer
app.use(function *(next) {
	var base = template.defaults.base;
	var ext = template.defaults.extname;
	
	var uri = this.path;
	if (uri === '/') {
		uri = 'index.html'; 
	} 
	var isTpl = uri.endsWith(ext);
	if (isTpl == true) { 
		var model = { }; 
		// 从模板内容里寻找入口JS文件<script src='.*' server-render />
		var fileText = fs.readFileSync(path.join(base, uri), 'utf-8');
		var mainScript = fileText.match(/<script\s*.[^>]*((server\-render.[^>]*src\s*\=\s*['"].[^'"]*['"])|(src\s*\=\s*['"].[^'"]*['"].[^>]*server\-render)).[^>]*\s*>\s*<\/script>/g);
		if (mainScript) {
			var _keys = mainScript[0].match(/server\-render\s*=\s*['"].[^'"]*['"]/g)[0].split('=')[1].trim().replace(/['"]/g, "").split(' ');
			if (_keys[0].trim() == '') {
				_keys[0] = 'html';
			}
			if (typeof(_keys[1]) == 'undefined' || _keys[1].trim() == '') {
				_keys[1] = 'ajax';
			}
			var _entry = mainScript[0].match(/src\s*=\s*['"].[^'"]*['"]/g)[0].split('=')[1].trim().replace(/['"]/g, "").split('?')[0];
			_entry = path.resolve(OPTS.statics_path, _entry);
			_entry = _entry.replace(path.resolve(OPTS.statics_path, './js'), '').replace(/\\/g, "/");
			var _r = require('./'+OPTS.compiled_path_name+_entry);
			model[_keys[0]] = _r.html;
			model[_keys[1]] = _r.ajax;
			model._ajax = JSON.stringify(_r.ajax);
			
			var newjs = [
				'<script>$.__cache = {{#_ajax}}</script>', 
				'\t<script type="text/javascript" src="js/jq-delegate.js"></script>', 
				'\t'+mainScript[0]
			].join('\r\n');
			
			fileText = fileText.replace(mainScript[0], newjs);
		} 
		
		var html = template.compile(fileText)(model);
		this.body = html;
		return;
	}
	
	yield next;
});

app.listen(3333);